#include "display.h"

struct display_block_s display_block[DISPLAY_BLOCK_MAX_CNT];

void display_block_init(void)   // Initialize display block
{
    for(int i = 0; i < DISPLAY_BLOCK_MAX_CNT; i++) {
        display_block[i].id = 0;
        display_block[i].frame = 0;
        display_block[i].col = 0;
        display_block[i].row = 0;
        display_block[i].inv_time_ms = 0;
        display_block[i].is_playing = false;
        for(int j = 0; j < DISPLAY_MAX_FRAME; j++) {
            for(int k = 0; k < DISPLAY_MAX_COL; k++) {
                for(int l = 0; l < DISPLAY_MAX_ROW; l++) {
                    display_block[i].data[j][k][l].red = 0;
                    display_block[i].data[j][k][l].green = 0;
                    display_block[i].data[j][k][l].blue = 0;
                }
            }
        }
    }
}

uint16_t get_idle_block(void)   // Get block that is not playing
{
    for(int i = 0; i < DISPLAY_BLOCK_MAX_CNT; i++) {
        if(display_block[i].is_playing == false) {
            return i;
        }
    }
    return DISPLAY_BLOCK_MAX_CNT;
}

void set_block_info(uint16_t id, uint16_t frame, uint8_t col, uint8_t row, uint16_t inv_time_ms)   // Set block information
{
    uint16_t block_index = get_idle_block();
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].id = id;
        display_block[block_index].frame = frame;
        display_block[block_index].col = col;
        display_block[block_index].row = row;
        display_block[block_index].inv_time_ms = inv_time_ms;
    }
}

uint16_t get_block_index(uint16_t id)   // Get block index
{
    for(int i = 0; i < DISPLAY_BLOCK_MAX_CNT; i++) {
        if(display_block[i].id == id) {
            return i;
        }
    }
    return DISPLAY_BLOCK_MAX_CNT;
}

void set_block_data(uint16_t id, uint16_t frame, uint8_t col, uint8_t row, uint8_t red, uint8_t green, uint8_t blue)   // Set block data
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].data[frame][col][row].red = red;
        display_block[block_index].data[frame][col][row].green = green;
        display_block[block_index].data[frame][col][row].blue = blue;
    }
}

void mark_block_playing(uint16_t id, bool is_playing)   // Mark block playing
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].is_playing = is_playing;
    }
}

void block_clear(uint16_t id)   // Clear block
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].id = 0;
        display_block[block_index].frame = 0;
        display_block[block_index].col = 0;
        display_block[block_index].row = 0;
        display_block[block_index].inv_time_ms = 0;
        display_block[block_index].is_playing = false;
        for(int j = 0; j < DISPLAY_MAX_FRAME; j++) {
            for(int k = 0; k < DISPLAY_MAX_COL; k++) {
                for(int l = 0; l < DISPLAY_MAX_ROW; l++) {
                    display_block[block_index].data[j][k][l].red = 0;
                    display_block[block_index].data[j][k][l].green = 0;
                    display_block[block_index].data[j][k][l].blue = 0;
                }
            }
        }
    }
}

struct bit_data_s get_pix_data(uint16_t id, uint16_t frame, uint8_t col, uint8_t row)   // Get pixel data
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        return display_block[block_index].data[frame][col][row];
    }
    struct bit_data_s data;
    data.red = 0;
    data.green = 0;
    data.blue = 0;
    return data;
}

uint16_t get_inv_time_ms(uint16_t id)   // Get inversion time in milliseconds
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        return display_block[block_index].inv_time_ms;
    }
    return 0;
}

uint16_t get_frame(uint16_t id)   // Get frame
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        return display_block[block_index].frame;
    }
    return 0;
}

uint8_t get_col(uint16_t id)   // Get column
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        return display_block[block_index].col;
    }
    return 0;
}

uint8_t get_row(uint16_t id)   // Get row
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        return display_block[block_index].row;
    }
    return 0;
}

uint8_t set_play_mode(uint16_t id, enum play_mode_e play_mode)   // Set play mode
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].play_mode = play_mode;
        return 0;
    }
    return 1;
}

uint8_t set_cycle_mode(uint16_t id, enum cycle_mode_e cycle_mode)   // Set cycle mode
{
    uint16_t block_index = get_block_index(id);
    if(block_index < DISPLAY_BLOCK_MAX_CNT) {
        display_block[block_index].cycle_mode = cycle_mode;
        return 0;
    }
    return 1;
}

